/**
 * Created by Administrator on 2016/11/30.
 */

var canvasScreen = (function(){
    function traverseNodes(node){
        console.log(node);
        //所有的元素节点
        for(var i = 0; i < node.length; i++){
            if(node[i].nodeName == "SCRIPT" || node[i].nodeName == "CANVAS") continue;
            drawElement(node[i]);
        }
    }
    function getReallyStyle(element){
        return element.currentStyle ? element.currentStyle : window.getComputedStyle(element, false);
    }
    var can;//绘制全屏的canvas
    var reallyCan;//选择部分截图的canvas
    var canvasBg;//遮罩层
    var ctx;//绘制全屏的画笔
    function canvasInit(){
        can = document.createElement("canvas");
        can.className = "canvas";
        can.style.position = "fixed";
        can.style.zIndex = "-1";
        can.style.top = "0";
        can.style.left = "0";
        can.width = window.innerWidth;
        can.height = document.body.scrollHeight;
        document.body.appendChild(can);
        ctx = can.getContext('2d');
    }
    function drawElement(node){
        var nodeCss = getReallyStyle(node);                //node的所有最终CSS样式集合
        var nodeLeft = node.getBoundingClientRect().left,  //node相对窗口的左边距
            nodeTop = node.getBoundingClientRect().top,//node相对窗口的上边距
            nodePaddingTop = parseInt(nodeCss.paddingTop),
            nodePaddingRight = parseInt(nodeCss.paddingRight),
            nodePaddingBottom = parseInt(nodeCss.paddingBottom),
            nodePaddingLeft = parseInt(nodeCss.paddingLeft),
            nodeWidth = parseInt(nodeCss.width),       //node本身的宽度
            nodeHeight = parseInt(nodeCss.height),     //node本身的高度
            nodeRealWidth = nodeWidth + nodePaddingLeft + nodePaddingRight,//加上padding的宽
            nodeRealHeight = nodeHeight + nodePaddingTop + nodePaddingBottom;//加上padding后的高
        var lineWidth;//笔触的宽度
        //如果节点是图片，则绘制这个图片节点
        if(node.nodeName == "IMG"){
            ctx.drawImage(node, nodeLeft, nodeTop, nodeWidth, nodeHeight)
        }
        //绘制背景颜色
        if(nodeCss.backgroundColor != "rgba(0, 0, 0, 0)" && nodeCss.backgroundColor != "rgb(255, 255, 255)" && nodeCss.backgroundColor != "transparent"){
            ctx.beginPath();
            ctx.lineWidth = parseInt(nodeCss.borderTopWidth) || 1;
            ctx.strokeStyle = nodeCss.backgroundColor;
            ctx.rect(nodeLeft, nodeTop, nodeRealWidth, nodeRealHeight);
            ctx.fillStyle = nodeCss.backgroundColor;
            ctx.fill();
            ctx.stroke();
        }
        //绘制背景图片
        if(nodeCss.backgroundImage != "none"){
            var img = document.createElement("img");
            //设置背景图片地址（由于此图片已经加载过，img.complete == true, 所以不用onload等图片加载）
            var s = nodeCss.backgroundImage.split("/").pop();
            img.src = s.substring(0, s.length - 2);
            //设置背景图片的位置(相对窗口)
            var imgX, imgY, imgW, imgH;
            imgW = parseInt(img.width);//宽
            imgH = parseInt(img.height);//高
            //背景图片是否重复
            if(nodeCss.backgroundRepeat == "no-repeat"){
                //左边距
                if(nodeCss.backgroundPositionX.indexOf("%") == -1){
                    imgX = nodeLeft + parseInt(nodeCss.backgroundPositionX);
                }else{
                    imgX = nodeLeft + (nodeWidth - imgW) * parseInt(nodeCss.backgroundPositionX) / 100;
                }
                //上边距
                if(nodeCss.backgroundPositionY.indexOf("%") == -1){
                    imgY = nodeTop + parseInt(nodeCss.backgroundPositionY);
                }else{
                    imgY = nodeTop + (nodeHeight - imgH) * parseInt(nodeCss.backgroundPositionY) / 100;
                }
                ctx.drawImage(img, imgX, imgY, imgW, imgH);
            }else{
                var xNum = Math.ceil(nodeWidth / imgW);//X方向的重复数
                var yNum = Math.ceil(nodeHeight / imgH);//Y方向的重复数
                //创建一个新的canvas完整的将背景图画出来
                var bgCan = document.createElement("canvas");
                bgCan.width =  xNum * imgW;
                bgCan.height = yNum * imgH;
                var bgCtx = bgCan.getContext('2d');
                //repeat-x只有一行
                if(nodeCss.backgroundRepeat == "repeat-x") yNum = 1;
                //repeat-y只有一列
                if(nodeCss.backgroundRepeat == "repeat-y") xNum = 1;
                for( var i = 0; i < yNum; i++){
                    for(var j = 0; j < xNum; j++){
                        console.log(j);
                        bgCtx.drawImage(img, imgW * j, imgH * i, imgW, imgH);
                    }
                }
                //将bgCan画出的完整背景图截取并画入原本的canvas
                ctx.drawImage(bgCan, 0, 0, nodeWidth, nodeHeight, nodeLeft, nodeTop, nodeWidth, nodeHeight);
            }
        }
        //绘制上边框
        if(nodeCss.borderTopWidth && nodeCss.borderTopWidth != "0px"){
            lineWidth = parseInt(nodeCss.borderTopWidth);
            drawLine(lineWidth, nodeCss.borderTopColor, nodeLeft, nodeTop, nodeLeft + nodeRealWidth + 2 * lineWidth, nodeTop);
        }
        //绘制右边框
        if(nodeCss.borderRightWidth && nodeCss.borderRightWidth != "0px") {
            lineWidth = parseInt(nodeCss.borderRightWidth);
            drawLine(lineWidth, nodeCss.borderRightColor, nodeLeft + nodeRealWidth + 2 * lineWidth, nodeTop, nodeLeft + nodeRealWidth + 2 * lineWidth, nodeTop + nodeRealHeight + 2 * lineWidth);
        }
        //绘制下边框
        if(nodeCss.borderBottomWidth && nodeCss.borderBottomWidth != "0px") {
            lineWidth = parseInt(nodeCss.borderBottomWidth);
            drawLine(lineWidth, nodeCss.borderBottomColor, nodeLeft, nodeTop + nodeRealHeight + lineWidth, nodeLeft + nodeRealWidth + 2 * lineWidth, nodeTop + nodeRealHeight + 2 * lineWidth);
        }
        //绘制左边框
        if(nodeCss.borderLeftWidth && nodeCss.borderLeftWidth != "0px") {
            lineWidth = parseInt(nodeCss.borderLeftWidth);
            drawLine(lineWidth, nodeCss.borderLeftColor, nodeLeft, nodeTop, nodeLeft, nodeTop + nodeRealHeight + 2 * lineWidth);
        }
        //绘制节点里的文本节点
        var child = node.childNodes;
        var contentX = nodeLeft + nodePaddingLeft + parseInt(nodeCss.borderLeftWidth);//content相对canvas的left
        var contentY = nodeTop + nodePaddingTop - parseInt(nodeCss.borderTopWidth) + parseInt(nodeCss.fontSize);//content相对canvas的top
        var lineNum = 0;//当前文本已经写了的行数(相当于Y方向的偏移量)
        var offsetX = 0;//X方向的偏移量
        for(var k = 0; k < child.length; k++){
            ctx.save();
            ctx.fillStyle = nodeCss.color;
            ctx.font = nodeCss.font ? nodeCss.font : nodeCss.fontSize + " " + nodeCss.fontFamily;
            //获取文本的行高，以便于换行
            var lineHeight = parseInt(nodeCss.lineHeight);
            if(lineHeight.toString() == "NaN"){
                lineHeight = parseInt(nodeCss.fontSize) * 1.4;
            }
            console.log(lineHeight);
            //判断当前节点类型，执行相应操作
            if(child[k].nodeType == 3 && /\S/.test(child[k].nodeValue)){
                //文本节点，绘制文本
                if(offsetX)console.log(offsetX);
                var returnData = canvasTextAutoLine(child[k].nodeValue, nodeWidth, contentX, contentY + lineHeight * lineNum, lineHeight, offsetX);
                offsetX = returnData.offsetX;//加上X方向的偏移量
                lineNum += returnData.lineNum;//加上行数
            }else if(child[k] && child[k].nodeName == "BR") {
                //节点是br，换行
                offsetX = 0; //X方向偏移量为零
                lineNum++;  //行数加一
            }else if(child[k].nextSibling && child[k].nextSibling.nodeName == "#text" && /\S/.test(child[k].nextSibling.nodeValue)){
                //下个节点是文本节点，设置下一个文本节点的首行X方向的偏移量
                offsetX = child[k].offsetLeft + child[k].offsetWidth - contentX;
            }
            ctx.restore();
        }
    }
    function drawLine(width, color, x, y, x1, y1, lineJoin){
        ctx.save();
        ctx.beginPath();
        ctx.lineJoin = lineJoin;
        ctx.lineWidth = width;
        ctx.strokeStyle = color;
        ctx.moveTo(x, y);
        ctx.lineTo(x1, y1);
        ctx.stroke();
        ctx.restore();
    }
    /*
     str:要绘制的字符串
     boxWidth:容器的宽度
     initX:绘制字符串起始x坐标
     initY:绘制字符串起始y坐标
     lineHeight:字行高
     */
    function canvasTextAutoLine(str, boxWidth, initX, initY, lineHeight, offsetX){
        var lineWidth = 0;     //每行文字的宽度
        var lastSubStrIndex= 0;
        var lineNum = 0;//这段文字的行数
        for(var i = 0; i < str.length; i++){
            lineWidth += ctx.measureText(str[i]).width;
            if(lineWidth > boxWidth - offsetX){
                //换行
                ctx.fillText(str.substring(lastSubStrIndex, i), initX + offsetX, initY);
                initY += lineHeight;
                offsetX = 0;
                lineWidth = 0;
                lastSubStrIndex = i;
                lineNum++;
            }
            if(i == str.length-1){
                ctx.fillText(str.substring(lastSubStrIndex,i + 1), initX + offsetX, initY);
            }
        }
        return {
            offsetX : lineWidth + offsetX,
            lineNum   : lineNum
        };
    }
    // Converts canvas to an image
    function convertCanvasToImage(canvas) {
        var image = new Image();
        image.src = canvas.toDataURL("image/png");
        return image;
    }
    return {
        screen : function(){
            //document 获取根元素
            var root = document.querySelectorAll("body *");
            canvasInit();
            //遍历所有的节点
            traverseNodes(root);
            //canvas的背景遮罩层
            canvasBg = document.createElement('div');
            canvasBg.style.width = "100%";
            canvasBg.style.height = "100%";
            canvasBg.style.position = "fixed";
            canvasBg.style.zIndex = "999";
            canvasBg.style.top = "0";
            canvasBg.style.left = "0";
            canvasBg.style.background = "rgba(0,0,0,0.5)";
            document.body.appendChild(canvasBg);
            console.log(canvasBg)
            canvasBg.innerHTML = "<div id='cancel_screen' style='position: absolute;top: 0;right: 0;width: 50px;height: 50px;text-indent: 20px;color:white;font-size: 30px;" +
                "font-family: cursive;background-color: rgba(0,0,0,0.6);border-bottom-left-radius: 50px;'>X</div> " +
            "<div id='choice_box' style='display: none;position: absolute'> " +
            "<button id='saveImageBtn' onclick='canvasScreen.saveImageInfo();'>保存为图片</button> " +
            "<button id='downloadImageBtn' onclick='canvasScreen.saveAsLocalImage()'>保存图片到本地</button> " +
            "</div>";
            var startX;
            var startY;
            var endX;
            var endY;
            var isStart = false;
            reallyCan = document.createElement("canvas");
            reallyCan.style.position = "fixed";
            reallyCan.style.zIndex = "1001";
            document.body.appendChild(reallyCan);
            var cancel = document.getElementById("cancel_screen");
            cancel.onclick = function(){
                document.body.removeChild(canvasBg);
                document.body.removeChild(reallyCan);
                document.body.removeChild(can);
                return false;
            };
            //退出截屏
            window.document.onmousedown = function(e){
                e = e ? e : window.event;
                console.log(e);
                if(e.toElement == cancel){
                    document.body.removeChild(canvasBg);
                    document.body.removeChild(reallyCan);
                    document.body.removeChild(can);
                    window.document.onmousedown = function(){};
                    return false;
                }
                startX = e.screenX;
                startY = e.screenY;
                reallyCan.style.top = startY - 66 + "px";
                reallyCan.style.left = startX + "px";
                isStart = true;
            };
            window.document.onmousemove = function(e){
                if(isStart){
                    e = e ? e : window.event;
                    endX = e.screenX;
                    endY = e.screenY;
                    reallyCan.width =  endX - startX;
                    reallyCan.height = endY - startY;
                    var bgCtx = reallyCan.getContext('2d');
                    bgCtx.drawImage(can, startX, startY - 66, endX - startX, endY - startY, 0, 0, endX - startX, endY - startY);
                    //reallyCan.style.border = "2px solid red";
                }
            };
            window.document.onmouseup = function(){
                if(isStart){
                    isStart = false;
                    window.document.onmousedown = function(e){};
                    var choiceBox = document.getElementById("choice_box");
                    choiceBox.style.display = "block";
                    choiceBox.style.top = endY - 66 + "px";
                    choiceBox.style.left = endX +  "px";
                }
            }
        },
        saveImageInfo : function () {
            //在空白页打开页面
            console.log(can)
            var image1 = can.toDataURL("image/png");
            var image = reallyCan.toDataURL("image/png");
            var w = window.open('about:blank','image from canvas');
            w.document.write("<img src='"+image+"' alt='from canvas'/>");
        },
        saveAsLocalImage : function  () {
            //保存图片到本地
            var image = can.toDataURL("image/png").replace("image/png", "image/octet-stream");
            window.location.href = image; // it will save locally
        }
    }
})();